package dao

import (
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"time"
)

type LanguageDao interface {
	Insert(ctx context.Context, language *Language) error
	FindByLangId(ctx context.Context, langID string) (*Language, error)
	List(ctx context.Context, page, pageSize int) ([]*Language, error)
	CheckExist(ctx context.Context, langID string) (*Language, error)
	Update(ctx context.Context, language *Language) error
	Save(ctx context.Context, language *Language) error
	Delete(ctx context.Context, id string) error
	GetEnabledLanguages(ctx context.Context) ([]*Language, error)
	Count(ctx *gin.Context) (int, error)
}

type GormLanguageDao struct {
	db *gorm.DB
}

func (dao *GormLanguageDao) Count(ctx *gin.Context) (int, error) {
	var count int64
	err := dao.db.WithContext(ctx).Model(&Language{}).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return int(count), nil
}

func NewLanguageDao(db *gorm.DB) LanguageDao {
	return &GormLanguageDao{db: db}
}

func (dao *GormLanguageDao) GetEnabledLanguages(ctx context.Context) ([]*Language, error) {
	var languages []*Language
	if err := dao.db.WithContext(ctx).Where("enabled = ?", true).Find(&languages).Error; err != nil {
		return nil, err
	}
	return languages, nil
}

func (dao *GormLanguageDao) Delete(ctx context.Context, id string) error {
	err := dao.db.WithContext(ctx).Where("lang_id = ?", id).Delete(&Language{}).Error
	if err != nil {
		return err
	}
	return nil
}

func (dao *GormLanguageDao) Update(ctx context.Context, language *Language) error {
	// 检查 lang_id 是否已经存在且 deleted_at 为 NULL
	existingLanguage, err := dao.CheckExist(ctx, language.LangID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("语言不存在: %s", language.LangID)
		}
		return fmt.Errorf("检查语言失败: %w", err)
	}
	if existingLanguage.LangID != language.LangID {
		return fmt.Errorf("语言 ID 不匹配: %s", language.LangID)
	}
	// 执行更新操作，更新所有字段
	rs := dao.db.WithContext(ctx).Model(&existingLanguage).Updates(map[string]interface{}{"name": language.Name, "dsc": language.Dsc, "enabled": language.Enabled})
	if rs.RowsAffected != 1 {
		return fmt.Errorf("更新语言失败: %w", rs.Error)
	}
	return nil
}

func (dao *GormLanguageDao) Save(ctx context.Context, language *Language) error {
	tx := dao.db.WithContext(ctx).Save(language)
	if tx.RowsAffected != 1 {
		return tx.Error
	}
	return nil
}

func (dao *GormLanguageDao) CheckExist(ctx context.Context, langID string) (*Language, error) {
	var existingLanguage Language
	err := dao.db.WithContext(ctx).Where("lang_id = ? AND deleted_at IS NULL", langID).First(&existingLanguage).Error
	if err != nil {
		return nil, err
	}
	return &existingLanguage, nil
}

func (dao *GormLanguageDao) List(ctx context.Context, page, pageSize int) ([]*Language, error) {
	var languages []*Language
	// 计算偏移量
	offset := (page - 1) * pageSize
	// 使用分页参数进行查询
	err := dao.db.WithContext(ctx).Offset(offset).Limit(pageSize).Find(&languages).Error
	if err != nil {
		return nil, err
	}
	return languages, err
}

func (dao *GormLanguageDao) Insert(ctx context.Context, language *Language) error {
	tx := dao.db.WithContext(ctx).Begin()
	if tx.Error != nil {
		return tx.Error
	}

	// 检查 lang_id 是否已经存在（包括软删除的记录）
	var existingLanguage Language
	result := tx.Unscoped().Where("lang_id = ?", language.LangID).First(&existingLanguage)

	if result.RowsAffected == 1 {
		if existingLanguage.DeletedAt.Valid {
			// 如果记录已被软删除，启用该记录
			if err := tx.Unscoped().Model(&existingLanguage).
				Updates(map[string]interface{}{
					"deleted_at": nil,
					"is_deleted": false,
					"enabled":    true,
				}).Error; err != nil {
				tx.Rollback()
				return err
			}
		} else {
			// 如果记录已存在且未被软删除，返回错误
			tx.Rollback()
			return fmt.Errorf("语言 %s 已存在", language.LangID)
		}
	} else if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		// 如果记录不存在，插入新记录
		if err := tx.Create(language).Error; err != nil {
			tx.Rollback()
			return err
		}
	} else {
		tx.Rollback()
		return result.Error
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return err
	}

	return nil
}

func (dao *GormLanguageDao) FindByLangId(ctx context.Context, langID string) (*Language, error) {
	var language Language
	err := dao.db.WithContext(ctx).Where("lang_id = ?", langID).Find(&language).Error
	if err != nil {
		return nil, err
	}
	return &language, nil
}

type BaseModel struct {
	ID        int64          `gorm:"primaryKey;autoIncrement" json:"id"`
	CreatedAt time.Time      `gorm:"column:add_time;autoCreateTime" json:"add_time"`
	UpdatedAt time.Time      `gorm:"column:update_time;autoUpdateTime" json:"update_time"`
	DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // GORM软删除用
	IsDeleted bool           `gorm:"column:is_deleted;default:false" json:"is_deleted"`
}

type Language struct {
	BaseModel
	LangID  string `gorm:"column:lang_id;type:varchar(20);uniqueIndex;not null;comment:'语言ID，如zh-CN/en-US'" json:"lang_id"`
	Name    string `gorm:"type:varchar(50);not null;comment:'语言名称，如 中文、英文'" json:"name"`
	Dsc     string `gorm:"column:dsc;type:varchar(20);comment:'描述'" json:"dsc"` // 添加 Dsc 字段
	Enabled bool   `gorm:"column:enabled;comment:'是否启用'" json:"enabled"`
}

// Translation 表示元素的多语言翻译信息

func (Language) TableName() string {
	return "language"
}
